﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace MichMan.Utilities.UnitTest
{
    public class CultureFormatProvider : CustomFormatProvider<CultureInfo>
    {
        public CultureFormatProvider()
            : base(ci => ci.ToString().Split('/').First())
        {
        }
    }

    [UriFormat("http://www.somedomain.com/{locale}/{version}/{path}")]
    public class AResource
    {
        [UriParam("locale")]
        public CultureInfo Culture { get; set; }

        [UriParam("version", FormatProviderType=typeof(CultureFormatProvider))]
        public int Version { get; set; }

        [UriParam("path")]
        public string Path { get; set; }

        [QueryParam("required", Required = true)]
        public string Required { get; set; }

        [QueryParam("optional")]
        public int? Optional { get; set; }

        [QueryParam("otherculture", FormatProviderType = typeof(CultureFormatProvider))]
        public CultureInfo OtherCulture { get; set; }

        [QueryParam("first", Order = 0)]
        public int First { get; set; }
    }

    [UriFormat("http://www.somedomain.com/lotsofparameters")]
    public class AResourceWithLotsOfParams
    {
        [QueryParam("first", Order = 1)]
        public int First { get; set; }
        [QueryParam("second", Order = 2)]
        public int Second { get; set; }
        [QueryParam("third", Order = 3)]
        public int Third { get; set; }

        [QueryParam("fourth1", Order = 4)]
        public int Forth1 { get; set; }
        [QueryParam("fourth2", Order = 4)]
        public int Forth2 { get; set; }

        [QueryParamList("a")]
        public List<int> AList { get; set; }
    }

    [TestClass]
    public class UriInfererTests
    {
        [TestMethod]
        public void UriInfererTest()
        {
            AResource res = new AResource()
            {
                Culture = CultureInfo.CurrentUICulture,
                OtherCulture = CultureInfo.CurrentUICulture,
                Version = 1,
                Path = "somerestmethod",
                Required = "Required",
            };

            Uri uri = UriInferer.InferUri(res);
            Assert.IsNotNull(uri, "Uri did not infer correctly.");
            Assert.IsFalse(String.IsNullOrWhiteSpace(uri.ToString()), "Uri did not infer correctly.");
            Assert.AreEqual(@"http://www.somedomain.com/en-US/1/somerestmethod?first=0&required=Required&otherculture=en-US",
                uri.ToString());
        }

        [TestMethod]
        public void UriParamTest()
        {
            AResourceWithLotsOfParams res = new AResourceWithLotsOfParams();
            res.AList = new List<int>() { 0, 1, 2, 3 };

            Uri uri = UriInferer.InferUri(res);
            Assert.IsNotNull(uri, "Uri did not infer correctly.");
            Assert.IsFalse(String.IsNullOrWhiteSpace(uri.ToString()), "Uri did not infer correctly.");
            Assert.AreEqual(@"http://www.somedomain.com/lotsofparameters?first=0&second=0&third=0&fourth1=0&fourth2=0&a=0&a=1&a=2&a=3",
                uri.ToString());
        }

        [TestMethod]
        public void UriInfererThrowTest()
        {
            AResource res = new AResource()
            {
                Culture = CultureInfo.CurrentUICulture,
                Version = 1,
                Path = "somerestmethod",
            };

            Uri uri = null;
            bool threw = false;
            try
            {
                // This should throw.
                uri = UriInferer.InferUri(res);
            }
            catch
            {
                threw = true;
            }
            Assert.IsTrue(threw, "UriInferer should have throw - required parameter not provided.");
            Assert.IsNull(uri, "Uri should be null - required parameter not provided.");
        }
    }
}
